﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace IRC.IRepairClouds.DataLayer
{
    public static class ReflectionHelper
    {
        private static object lockGetPropertyInfo = new object();
        private static object lockGetPropertyInfoT = new object();
        private static object lockGetPropertyValue = new object();
        private static object lockSetPropertyValue = new object();

        public static PropertyInfo GetPropertyInfo(object o, string propertyPath, ref object parentObject)
        {
            lock (lockGetPropertyInfo) {
                return GetPropertyInfoI(o, propertyPath, ref parentObject);
            }
        }

        private static PropertyInfo GetPropertyInfoI(object o, string propertyPath, ref object parentObject)
        {
            parentObject = null;
            if ((o == null) || string.IsNullOrEmpty(propertyPath)) {
                return null;
            }
            if (propertyPath.Contains(".")) {
                string property = propertyPath.Substring(0, propertyPath.IndexOf("."));
                string path = propertyPath.Substring(propertyPath.IndexOf(".") + 1);
                PropertyInfo pi = o.GetType().GetProperty(property);
                if (pi == null) {
                    return null;
                }
                return GetPropertyInfoI(pi.GetValue(o, null), path, ref parentObject);
            }
            parentObject = o;
            return o.GetType().GetProperty(propertyPath);
        }

        public static Settable<object> GetPropertyValue(object o, string propertyPath)
        {
            lock (lockGetPropertyValue) {
                return GetPropertyValueI(o, propertyPath);
            }
        }

        private static Settable<object> GetPropertyValueI(object o, string propertyPath)
        {
            PropertyInfo pi = null;
            object parentObject = null;
            pi = GetPropertyInfo(o, propertyPath, ref parentObject);
            if ((pi != null) && (parentObject != null)) {
                return new Settable<object>(pi.GetValue(parentObject, null));
            }
            return Settable<object>.NotSet;
        }
    }
}
